const callbacks = []
const isRunning = []
export function nextTick(fn, ctx) {
  callbacks.push(() => {
    fn.call(ctx)
  })
  if (!isRunning) {
    isRunning = true
    timerFunc()
  }
  return new Promise(resolve => {
    resolve()
  })
}

let timerFunc = null
let counter = 1
if (typeof Promise != 'undefined') {
  timerFunc = () => Promise.resolve().then(() => flushCallbacks())
} else if (typeof MutationObserver != 'undefined') {
  const observer = new MutationObserver(flushCallbacks)
  const textNode = document.createTextNode(String(counter))
  observer.observe(textNode, { characterData: true })
  timerFunc = () => {
    counter = (counter + 1) % 2
    textNode.data = String(counter)
  }
} else if (typeof setImmediate != 'undefined') {
  timerFunc = () => setInterval(flushCallbacks)
} else {
  timerFunc = () => setTimeout(flushCallbacks)
}

function flushCallbacks() {
  while (callbacks.length) {
    const callback = callbacks.shift()
    callback()
  }
  isRunning = false
}
